package core

import (
	"net/http"
	"log"
	"fmt"
	"reflect"
	"runtime/debug"
)

type Server struct {
	Port              int
	Context           string
	Router            Router
	Render            Render
	DefaultController Controller
}

func (this *Server) AddController(urlPath string, controller Controller) *Server {
	if this.Router == nil {
		this.Router = DefaultRouter
	}
	this.Router.Add(urlPath, controller)
	return this
}

func (this *Server) Start() {
	if this.Router == nil {
		this.Router = DefaultRouter
	}
	if this.Render == nil {
		this.Render = DefaultRender
	}
	if this.DefaultController == nil {
		this.DefaultController = &Inner404Controller{}
	}
	if len(this.Context) == 0 {
		this.Context = "/"
	}
	log.Printf("Server.Port = %d", this.Port)
	log.Printf("Server.Context = %s", this.Context)
	log.Printf("Server.Router = %s", reflect.TypeOf(this.Router).String())
	log.Printf("Server.Render = %s", reflect.TypeOf(this.Render).String())
	log.Printf("Server.DefaultController = %s", reflect.TypeOf(this.DefaultController).String())
	for urlPath, controller := range this.Router.List() {
		log.Printf("route info: %s -> %s", urlPath, reflect.TypeOf(controller).String())
	}

	http.HandleFunc(this.Context, func(response http.ResponseWriter, request *http.Request) {
		controller := this.Router.Match(request.URL.Path)
		var my_response *HttpResponse = nil
		if controller == nil {
			my_response = this.DefaultController.Handle(&HttpRequest{})
		} else {
			my_response = controller.Handle(&HttpRequest{request})
		}
		this.Render.Render(my_response, response)
	})
	err := http.ListenAndServe(fmt.Sprintf(":%d", this.Port), nil)
	log.Printf("Server Started!")

	if err != nil {
		debug.PrintStack()
	}
}
